#ifndef CHARMM_PARAM_H_
#define CHARMM_PARAM_H_
#include "io_charmm_inp.h"
#include "nonbonded.h"
#include "elemtab.h"
typedef struct bond_param {
  real r0, kr;
  int shaked;
} bond_param_t;

typedef struct angle_param {
  real r0ub, kub;
  real theta0, ktheta;
  int shaked;
} angle_param_t;

typedef struct tori_param {
  real kphi, phi0, n;
} tori_param_t;

typedef struct tori_param_range {
  int start, count;
} tori_param_range_t;
typedef struct tori_param_tab {
  tori_param_range_t *range;
  tori_param_t *param;
} tori_param_tab_t;
typedef struct temp_dihed_param {
  typeint itype, jtype, ktype, ltype;
  real kphi, phi0, n;
} temp_dihed_param_t;
typedef struct charmm_impr_param {
  real kphi, phi0;
} harmonic_impr_param_t;

typedef struct charmm_param {
  int ntypes;
  nonbonded_param_t nonb;
  bond_param_t *bond;
  angle_param_t *angle;
  tori_param_tab_t tori;
  harmonic_impr_param_t *impr;
} charmm_param_t;

INLINE int impr_wildcard_level(const temp_dihed_param_t *a) {
  if (a->itype == ELEMTAB_WILD && a->jtype == ELEMTAB_WILD || a->ktype == ELEMTAB_WILD && a->ltype == ELEMTAB_WILD) {
    return 4;
  }
  if (a->itype == ELEMTAB_WILD && a->ltype == ELEMTAB_WILD) {
    return 3;
  }
  if (a->itype == ELEMTAB_WILD) {
    return 2;
  }
  if (a->jtype == ELEMTAB_WILD && a->ktype == ELEMTAB_WILD) {
    return 1;
  }
  return 0;
}
//function signatures
bond_param_t *build_bond_params(charmm_rawparam_t *inp, elemtab_t *elemtab);
angle_param_t *build_angle_params(charmm_rawparam_t *inp, elemtab_t *elemtab);
void build_tori_params_tab(tori_param_tab_t *tab, charmm_rawparam_t *inp, elemtab_t *elemtab);
harmonic_impr_param_t *build_impr_params(charmm_rawparam_t *inp, elemtab_t *elemtab);
void build_nonbonded_param(nonbonded_param_t *param, real rcut, real rsw, real coul_const, real scale14, charmm_rawparam_t *inp, elemtab_t *elemtab);
void build_param(charmm_param_t *param, charmm_rawparam_t *inp, elemtab_t *elemtab, real rcut, real rsw, real coul_const, real scale14);
//end function signatures
#endif
